package com.sduept.nwld.dataserver.manager.fault;

import com.sduept.bigdata.fault.entity.FaultRecord;
import com.sduept.bigdata.fault.entity.FaultSourceUploadInfo;
import com.sduept.bigdata.fault.manager.FaultRecordQueryManager;
import com.sduept.bigdata.fault.manager.FaultSourceQueryService;
import com.sduept.core.dao.SuperDAO;
import com.sduept.nwld.dataserver.manager.cim.CimManager;
import com.sduept.nwld.fault.analysis.model.FaultUploadInfoDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class FaultSourceQueryManager {
	@Autowired
	private SuperDAO dao;
	@Autowired
	private FaultRecordQueryManager fqm;
	@Autowired
	private CimManager cm;
	@Autowired
	private FaultSourceQueryService service;

	private static final Map<String, IFaultUploadTransform> strategyMap = new HashMap<>();
	private static final String busType = "母线";
	private static final String lineType = "线路";
	private static final String powerType = "变压器";

	/**
	 * 根据电压等级、起止时间获得故障上送信息
	 * @param voltage
	 * @param start
	 * @param end
	 * @return
	 */
	public List<FaultUploadInfoDTO> getFaultUploadInfoDTOByEtypeVoltageDate(Integer voltage, String etype, Date start,
			Date end) {
		String sql = "SELECT t.* FROM t_fault_source_upload_info t LEFT JOIN t_cim_fault s ON t.faultId=s.id WHERE s.etype=? and s.voltage=? AND s.faultTime BETWEEN ? AND ? ORDER BY s.faultTime";
		List<FaultSourceUploadInfo> list = dao.nativeQuery(FaultSourceUploadInfo.class, sql,
				new Object[] { etype, voltage, start, end });
		return transform(etype, list);
	}

	/**
	 * 根据电压等级、起止时间获得故障上送信息
	 * @param voltage
	 * @param start
	 * @param end
	 * @return
	 */
	public List<FaultSourceUploadInfo> getFaultUploadInfoByEtypeVoltageDate(Integer voltage, String etype, Date start,
			Date end) {
		String sql = "SELECT t.* FROM t_fault_source_upload_info t  LEFT JOIN t_cim_fault s ON t.faultId=s.id WHERE s.etype=? and s.voltage=? AND s.faultTime BETWEEN ? AND ?";
		List<FaultSourceUploadInfo> infos = dao.nativeQuery(FaultSourceUploadInfo.class, sql,
				new Object[] { etype, voltage, start, end });
		List<FaultSourceUploadInfo> uploadInfos = service.completeFaultSourceUploadInfo(infos);
		return uploadInfos;
	}

	/**
	 *    根据故障记录获得上送信息
	 * @param fr
	 * @return
	 */
	public List<FaultUploadInfoDTO> getFaultUploadInfoDTOByFaultRecord(FaultRecord fr) {
		List<FaultSourceUploadInfo> list = dao.findByCondition(FaultSourceUploadInfo.class, "faultId=?", fr.getId());
		return transform(fr.getEtype(), list);
	}

	/**
	 * 	根据故障记录id获得上送信息
	 * @param fr
	 * @return
	 */
	public List<FaultUploadInfoDTO> getFaultUploadInfoDTOByFaultRecord(String frid) {
		FaultRecord fr = fqm.findById(frid);
		return getFaultUploadInfoDTOByFaultRecord(fr);
	}

	/**
	 * 根据设备类型、起止时间，获得故障上送信息
	 * @param start
	 * @param end
	 * @return
	 */
	public List<FaultUploadInfoDTO> getFaultUploadInfoDTOByDate(String etype, Date start, Date end) {
		String sql = "SELECT t.* FROM t_fault_source_upload_info t  LEFT JOIN t_cim_fault s ON t.faultId=s.id WHERE s.etype=? AND s.faultTime BETWEEN ? AND ?";
		List<FaultSourceUploadInfo> list = dao.nativeQuery(FaultSourceUploadInfo.class, sql,
				new Object[] { etype, start, end });
		return transform(etype, list);
	}

	/**
	 * 根据条件获取线路故障的FaultSourceUploadInfo
	 * @param startDate
	 * @param endDate
	 * @param voltage
	 * @param etype
	 * @return
	 */
	public List<FaultSourceUploadInfo> findLineFaultUploadInfoByDateAndVoltage(Date startDate, Date endDate,
			Integer voltage, String etype) {
		List<FaultRecord> faults = fqm.findFaultByTimeEtypeVoltage(startDate, endDate, voltage, etype);
		List<FaultSourceUploadInfo> list = new ArrayList<FaultSourceUploadInfo>();
		for (FaultRecord fr : faults) {
			list.addAll(findFaultSourceUploadInfo(fr.getId()));
		}
		return list;
	}

	/**
	 * 根据年、月获取故障上送信息
	 * @param year
	 * @param month
	 * @return
	 */
	public List<FaultSourceUploadInfo> findFaultSourceUploadInfo(Integer year, Integer month) {
		String sql ="select u.id,u.name,u.deviceType,u.equipId,u.faultId,u.month,u.stationName,u.uploadMethod,u.uploadType,u.year,u.stationId,p.dispatchUnit,p.maintenanceUnit from t_fault_source_upload_info u left join t_cim_fault f on u.faultId=f.id left join t_primary_equipment_ledger  p " + 
				"on f.equipment_id=p.cimId  where f.etype='线路'  and f.`status`=0  and p.dispatchUnit is not null and u.year=? and u.month=? ";
		List<FaultSourceUploadInfo> result =  dao.nativeQuery(sql, new Object[] {year,month}, FaultSourceUploadInfo.class);
		return result;
	}

	/**
	 * 根据年、月（区间）获取故障上送信息，返回已设置了调度、运维单位的记录
	 * @param year
	 * @param startMonth
	 * @param endMonth
	 * @return
	 */
	public List<FaultSourceUploadInfo> findFaultSourceUploadInfo(Integer year, Integer startMonth, Integer endMonth) {
		String sql ="select u.id,u.name,u.deviceType,u.equipId,u.faultId,u.month,u.stationName,u.uploadMethod,u.uploadType,u.year,u.stationId,p.dispatchUnit,p.maintenanceUnit from t_fault_source_upload_info u left join t_cim_fault f on u.faultId=f.id left join t_primary_equipment_ledger  p " + 
				"on f.equipment_id=p.cimId  where f.etype='线路'  and f.`status`=0  and p.dispatchUnit is not null and u.year=? and u.month>=? and  u.month<=?";
		List<FaultSourceUploadInfo> result =  dao.nativeQuery(sql, new Object[] {year,startMonth,endMonth}, FaultSourceUploadInfo.class);
		return result;
	}

	/**
	 *      对象转换FaultSourceUploadInfo  --->	FaultUploadInfoDTO
	 * @param info
	 * @return
	 */
	protected List<FaultUploadInfoDTO> transform(String etype, List<FaultSourceUploadInfo> infos) {
		IFaultUploadTransform transform = strategyMap.get(etype);
		if (transform == null) {
			synchronized (strategyMap) {
				transform = strategyMap.get(etype);
				if (transform == null) {
					if (lineType.equals(etype)) {
						strategyMap.put(lineType, new LineFaultUploadTransform());
					} else if (busType.equals(etype)) {
						strategyMap.put(busType, new BusbarFaultUploadTransform());
					} else if (powerType.equals(etype)) {
						strategyMap.put(powerType, new TransformerFaultUploadTransform());
					} else {
						return new ArrayList<FaultUploadInfoDTO>();
					}
				}
				transform = strategyMap.get(etype);
			}
		}
		List<FaultSourceUploadInfo> uploadInfos = service.completeFaultSourceUploadInfo(infos);
		List<FaultUploadInfoDTO> result = transform.transform(uploadInfos);
		sortListByFaultTime(result);
		return result;
	}

	/**
	 * 根据故障id获取FaultSourceUploadInfo
	 * @param faultId
	 * @return
	 */
	private List<FaultSourceUploadInfo> findFaultSourceUploadInfo(String faultId) {
		List<FaultSourceUploadInfo> infos = dao.findByCondition(FaultSourceUploadInfo.class, "faultId = ?", faultId);
		List<FaultSourceUploadInfo> lt = service.completeFaultSourceUploadInfo(infos);
		return lt;
	}

	/**
		 * 按照故障时间排序
		 * @param result
		 */
		private void sortListByFaultTime(List<FaultUploadInfoDTO> result) {
			Collections.sort(result, new Comparator<FaultUploadInfoDTO>() {
				@Override
				public int compare(FaultUploadInfoDTO info1, FaultUploadInfoDTO info2) {
					Date s1 = info1.getFaultTime();
					Date s2 = info2.getFaultTime();
	//				return s1.compareTo(s2);
					long t1 = s1.getTime();
					long t2 = s2.getTime();
					if (t1 < t2) {
						return 1;
					} else if (t1 > t2) {
						return -1;
					} else {
						return 0;
					}
				}
			});
		}

	private final class WhereBuilder {
		private StringBuilder sb = new StringBuilder();

		private String build() {
			return sb.toString();
		}

		public WhereBuilder buildLp() {
			sb.append(" ( ");
			return this;
		}

		public WhereBuilder buildRp() {
			sb.append(" )");
			return this;
		}

		public WhereBuilder buildFaultIdSql() {
			sb.append(" faultId = ? ");
			return this;
		}

		public WhereBuilder buildFaultYearSql() {
			sb.append(" year = ? ");
			return this;
		}

		public WhereBuilder buildFaultMonthSql() {
			sb.append(" month = ? ");
			return this;
		}

		// 设备类型：0：录波器，1：主保护， 2：断路器保护，3：非电量保护
		public WhereBuilder buildFaultDeviceTypeSql() {
			sb.append(" deviceType = ? ");
			return this;
		}

		// 上送类型：0：录波，1：动作元件
		public WhereBuilder buildFaultUploadTypeSql() {
			sb.append(" uploadType = ? ");
			return this;
		}

		// 集中录波
		public WhereBuilder buildCenterWaveSql() {
			sb.append(" deviceType = 0 and uploadType = 0 ");
			return this;
		}

		// 主保护录波
		public WhereBuilder buildProtectWaveSql() {
			sb.append(" deviceType = 1 and uploadType = 0 ");
			return this;
		}

		// 断路器保护录波
		public WhereBuilder buildBreakWaveSql() {
			sb.append(" deviceType = 2 and uploadType = 0 ");
			return this;
		}

		// 主保护事件
		public WhereBuilder buildProtectEventSql() {
			sb.append(" deviceType = 1 and uploadType = 1 ");
			return this;
		}

		// 断路器保护事件
		public WhereBuilder buildBreakEventSql() {
			sb.append(" deviceType = 2 and uploadType = 1 ");
			return this;
		}

		public WhereBuilder and() {
			sb.append(" AND ");
			return this;
		}

		public WhereBuilder or() {
			sb.append(" OR ");
			return this;
		}

		public WhereBuilder buildFaultMonthBetweenSql() {
			sb.append(" month between ? and ? ");
			return this;
		}
	}

}
